home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / files.c < prev    next >
C/C++ Source or Header  |  1993-01-25  |  22KB  |  1,005 lines

  1. /*    SCCS Id: @(#)files.c    3.1    92/12/07    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #include <ctype.h>
  8.  
  9. #if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C)
  10. #include <fcntl.h>
  11. #endif
  12. #if defined(UNIX) || defined(VMS)
  13. #include <errno.h>
  14. # ifndef SKIP_ERRNO
  15. extern int errno;
  16. # endif
  17. #include <signal.h>
  18. #endif
  19.  
  20. #if defined(MSDOS) || defined(OS2) || defined(TOS)
  21. # ifndef GNUDOS
  22. #include <sys\stat.h>
  23. # else
  24. #include <sys/stat.h>
  25. # endif
  26. #endif
  27. #ifndef O_BINARY    /* used for micros, no-op for others */
  28. # define O_BINARY 0
  29. #endif
  30.  
  31. #ifdef MFLOPPY
  32. char bones[FILENAME];        /* pathname of bones files */
  33. char lock[FILENAME];        /* pathname of level files */
  34. #else
  35. static char bones[] = "bonesnn.xxxx";
  36. # ifdef VMS
  37. char lock[PL_NSIZ+17] = "1lock"; /* long enough for _uid+name+.99;1 */
  38. # else
  39. char lock[PL_NSIZ+14] = "1lock"; /* long enough for uid+name+.99 */
  40. # endif
  41. #endif
  42.  
  43. #ifdef MAC
  44. #include <files.h>
  45. MacDirs theDirs ;
  46. #endif
  47.  
  48. #ifdef UNIX
  49. #define SAVESIZE    (PL_NSIZ + 13)    /* save/99999player.e */
  50. #else
  51. # ifdef VMS
  52. #define SAVESIZE    (PL_NSIZ + 22)    /* [.save]<uid>player.e;1 */
  53. # else
  54. #define SAVESIZE    FILENAME    /* from macconf.h or pcconf.h */
  55. # endif
  56. #endif
  57.  
  58. char SAVEF[SAVESIZE];    /* holds relative path of save file from playground */
  59. #ifdef MICRO
  60. char SAVEP[SAVESIZE];    /* holds path of directory for save file */
  61. #endif
  62. #ifdef AMIGA
  63. extern char PATH[];    /* see sys/amiga/amidos.c */
  64. #endif
  65.  
  66. static char * FDECL(set_bonesfile_name, (char *,d_level*));
  67.  
  68. /* fopen a file, with OS-dependent bells and whistles */
  69. FILE *
  70. fopen_datafile(filename, mode)
  71. const char *filename, *mode;
  72. {
  73.     FILE *fp;
  74. #ifdef AMIGA
  75.     fp = fopenp(filename, mode);
  76. #else
  77. # ifdef VMS    /* essential to have punctuation, to avoid logical names */
  78.     char tmp[BUFSIZ];
  79.  
  80.     if (!index(filename, '.') && !index(filename, ';'))
  81.         filename = strcat(strcpy(tmp, filename), ";0");
  82.     fp = fopen(filename, mode, "mbc=16");
  83. # else
  84.     fp = fopen(filename, mode);
  85. # endif
  86. #endif
  87.     return fp;
  88. }
  89.  
  90.  
  91. /* ----------  BEGIN LEVEL FILE HANDLING ----------- */
  92.  
  93. #ifdef MFLOPPY
  94. /* Set names for bones[] and lock[] */
  95. void
  96. set_lock_and_bones()
  97. {
  98.     if (!ramdisk) {
  99.         Strcpy(levels, permbones);
  100.         Strcpy(bones, permbones);
  101.     }
  102.     append_slash(permbones);
  103.     append_slash(levels);
  104.     append_slash(bones);
  105.     Strcat(bones, "bonesnn.*");
  106.     Strcpy(lock, levels);
  107.     Strcat(lock, alllevels);
  108.     return;
  109. }
  110. #endif /* MFLOPPY */
  111.  
  112.  
  113. /* Construct a file name for a level-type file, which is of the form
  114.  * something.level (with any old level stripped off).
  115.  * This assumes there is space on the end of 'file' to append
  116.  * a two digit number.  This is true for 'level'
  117.  * but be careful if you use it for other things -dgk
  118.  */
  119. void
  120. set_levelfile_name(file, lev)
  121. char *file;
  122. int lev;
  123. {
  124.     char *tf;
  125.  
  126.     tf = rindex(file, '.');
  127.     if (!tf) tf = eos(file);
  128.     Sprintf(tf, ".%d", lev);
  129. #ifdef VMS
  130.     Strcat(tf, ";1");
  131. #endif
  132.     return;
  133. }
  134.  
  135. int
  136. create_levelfile(lev)
  137. int lev;
  138. {
  139.     int fd;
  140.  
  141.     set_levelfile_name(lock, lev);
  142.  
  143. #if defined(MICRO)
  144.     /* Use O_TRUNC to force the file to be shortened if it already
  145.      * exists and is currently longer.
  146.      */
  147.     fd = open(lock, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
  148. #else
  149. #ifdef MAC
  150.     fd = maccreat ( lock , LEVL_TYPE ) ;
  151. #else /* MAC */
  152.     fd = creat(lock, FCMASK);
  153. #endif /* MAC */
  154. #endif /* MICRO */
  155.  
  156.     return fd;
  157. }
  158.  
  159.  
  160. int
  161. open_levelfile(lev)
  162. int lev;
  163. {
  164.     int fd;
  165.  
  166.     set_levelfile_name(lock, lev);
  167. #ifdef MFLOPPY
  168.     /* If not currently accessible, swap it in. */
  169.     if (fileinfo[lev].where != ACTIVE)
  170.         swapin_file(lev);
  171. #endif
  172. # ifdef MAC
  173.     fd = macopen ( lock , O_RDONLY | O_BINARY , LEVL_TYPE ) ;
  174. # else /* MAC */
  175.     fd = open(lock, O_RDONLY | O_BINARY, 0);
  176. # endif /* MAC */
  177.     return fd;
  178. }
  179.  
  180.  
  181. void
  182. delete_levelfile(lev)
  183. int lev;
  184. {
  185.     set_levelfile_name(lock, lev);
  186.     (void) unlink(lock);
  187. }
  188.  
  189.  
  190. void
  191. clearlocks()
  192. {
  193. #ifdef MFLOPPY
  194.     eraseall(levels, alllevels);
  195. # ifndef AMIGA
  196.     if (ramdisk)
  197.         eraseall(permbones, alllevels);
  198. # endif
  199. #else
  200.     register int x;
  201.  
  202. # if defined(UNIX) || defined(VMS)
  203.     (void) signal(SIGHUP, SIG_IGN);
  204. # endif
  205.     for (x = maxledgerno(); x >= 0; x--)
  206.         delete_levelfile(x);    /* not all levels need be present */
  207. #endif
  208. }
  209.  
  210. /* ----------  END LEVEL FILE HANDLING ----------- */
  211.  
  212.  
  213. /* ----------  BEGIN BONES FILE HANDLING ----------- */
  214.  
  215. static char *
  216. set_bonesfile_name(file, lev)
  217. char *file;
  218. d_level *lev;
  219. {
  220.     char *dptr = rindex(file, '.');
  221.     s_level *sptr;
  222.  
  223.     if (!dptr) dptr = eos(file);
  224.     *(dptr-2) = dungeons[lev->dnum].boneid;
  225. #ifdef MULDGN
  226.     *(dptr-1) = In_quest(lev) ? pl_character[0] : '0';
  227. #else
  228.     *(dptr-1) = '0';
  229. #endif
  230.     if ((sptr = Is_special(lev)) != 0)
  231.         Sprintf(dptr, ".%c", sptr->boneid);
  232.     else
  233.         Sprintf(dptr, ".%d", lev->dlevel);
  234. #ifdef VMS
  235.     Strcat(dptr, ";1");
  236. #endif
  237.     return(dptr-2);
  238. }
  239.  
  240. int
  241. create_bonesfile(lev, bonesid)
  242. d_level *lev;
  243. char **bonesid;
  244. {
  245.     int fd;
  246.  
  247.     *bonesid = set_bonesfile_name(bones, lev);
  248.  
  249. #ifdef MICRO
  250.     /* Use O_TRUNC to force the file to be shortened if it already
  251.      * exists and is currently longer.
  252.      */
  253.     fd = open(bones, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK);
  254. #else
  255. # ifdef MAC
  256.     fd = maccreat ( bones , BONE_TYPE ) ;
  257. # else /* MAC */
  258.     fd = creat(bones, FCMASK);
  259. # endif /* MAC */
  260. #  if defined(VMS) && !defined(SECURE)
  261.     /*
  262.        Re-protect bones file with world:read+write+execute+delete access.
  263.        umask() doesn't seem very reliable; also, vaxcrtl won't let us set
  264.        delete access without write access, which is what's really wanted.
  265.        Can't simply create it with the desired protection because creat
  266.        ANDs the mask with the user's default protection, which usually
  267.        denies some or all access to world.
  268.      */
  269.     (void) chmod(bones, FCMASK | 007);  /* allow other users full access */
  270. #  endif /* VMS && !SECURE */
  271. #endif /* MICRO */
  272.  
  273.     return fd;
  274. }
  275.  
  276.  
  277. int
  278. open_bonesfile(lev, bonesid)
  279. d_level *lev;
  280. char **bonesid;
  281. {
  282.     int fd;
  283.  
  284.     *bonesid = set_bonesfile_name(bones, lev);
  285.     uncompress(bones);    /* no effect if nonexistent */
  286. #ifdef MAC
  287.     fd = macopen ( bones , O_RDONLY | O_BINARY , BONE_TYPE ) ;
  288. #else
  289.     fd = open(bones, O_RDONLY | O_BINARY, 0);
  290. #endif
  291.     return fd;
  292. }
  293.  
  294.  
  295. int
  296. delete_bonesfile(lev)
  297. d_level *lev;
  298. {
  299.     (void) set_bonesfile_name(bones, lev);
  300.     return !(unlink(bones) < 0);
  301. }
  302.  
  303.  
  304. /* assume we're compressing the recently read or created bonesfile, so the
  305.  * file name is already set properly */
  306. void
  307. compress_bonesfile()
  308. {
  309.     compress(bones);
  310. }
  311.  
  312. /* ----------  END BONES FILE HANDLING ----------- */
  313.  
  314.  
  315. /* ----------  BEGIN SAVE FILE HANDLING ----------- */
  316.  
  317. /* set savefile name in OS-dependent manner from pre-existing plname,
  318.  * avoiding troublesome characters */
  319. void
  320. set_savefile_name()
  321. {
  322. #ifdef VMS
  323.     Sprintf(SAVEF, "[.save]%d%s", getuid(), plname);
  324.     regularize(SAVEF+7);
  325.     Strcat(SAVEF, ";1");
  326. #else
  327. # ifdef MICRO
  328.     Strcpy(SAVEF, SAVEP);
  329.     {
  330.         int i = strlen(SAVEP);
  331. #  ifdef AMIGA
  332.         /* plname has to share space with SAVEP and ".sav" */
  333.         (void)strncat(SAVEF, plname, FILENAME - i - 4);
  334. #  else
  335.         (void)strncat(SAVEF, plname, 8);
  336. #  endif
  337.         regularize(SAVEF+i);
  338.     }
  339.     Strcat(SAVEF, ".sav");
  340. # else
  341.     Sprintf(SAVEF, "save/%d%s", (int)getuid(), plname);
  342.     regularize(SAVEF+5);    /* avoid . or / in name */
  343. # endif
  344. #endif
  345. }
  346.  
  347. #ifdef INSURANCE
  348. void
  349. save_savefile_name(fd)
  350. int fd;
  351. {
  352.     (void) write(fd, (genericptr_t) SAVEF, sizeof(SAVEF));
  353. }
  354. #endif
  355.  
  356.  
  357. #if defined(WIZARD) && !defined(MICRO)
  358. /* change pre-existing savefile name to indicate an error savefile */
  359. void
  360. set_error_savefile()
  361. {
  362. # ifdef VMS
  363.       {
  364.     char *semi_colon = rindex(SAVEF, ';');
  365.     if (semi_colon) *semi_colon = '\0';
  366.       }
  367.     Strcat(SAVEF, ".e;1");
  368. # else
  369. #ifdef MAC
  370.     Strcat(SAVEF, "-e");
  371. #else
  372.     Strcat(SAVEF, ".e");
  373. #endif
  374. # endif
  375. }
  376. #endif
  377.  
  378.  
  379. /* create save file, overwriting one if it already exists */
  380. int
  381. create_savefile()
  382. {
  383.     int fd;
  384. # ifdef AMIGA
  385.     fd = ami_wbench_getsave(O_WRONLY | O_CREAT | O_TRUNC);
  386. # else
  387. #  ifdef MICRO
  388.     fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
  389. #  else
  390. #   ifdef MAC
  391.     fd = creat(SAVEF, SAVE_TYPE);
  392. #   else /* MAC */
  393.     fd = creat(SAVEF, FCMASK);
  394. #   endif /* MAC */
  395. #   if defined(VMS) && !defined(SECURE)
  396.     /*
  397.        Make sure the save file is owned by the current process.  That's
  398.        the default for non-privileged users, but for priv'd users the
  399.        file will be owned by the directory's owner instead of the user.
  400.      */
  401. #    ifdef getuid    /*(see vmsunix.c)*/
  402. #     undef getuid
  403. #    endif
  404.     (void) chown(SAVEF, getuid(), getgid());
  405. #   endif /* VMS && !SECURE */
  406. #  endif
  407. # endif
  408.  
  409.     return fd;
  410. }
  411.  
  412.  
  413. /* open savefile for reading */
  414. int
  415. open_savefile()
  416. {
  417.     int fd;
  418.  
  419. #ifdef AMIGA
  420.     fd = ami_wbench_getsave(O_RDONLY);
  421. #else
  422. # ifdef MAC
  423.     fd = macopen ( SAVEF , O_RDONLY , SAVE_TYPE ) ;
  424. # else /* MAC */
  425.     fd = open(SAVEF, O_RDONLY, 0);
  426. # endif /* MAC */
  427. #endif /* AMIGA */
  428.     return fd;
  429. }
  430.  
  431.  
  432. /* delete savefile */
  433. int
  434. delete_savefile()
  435. {
  436. #ifdef AMIGA
  437.     ami_wbench_unlink(SAVEF);
  438. #endif
  439.     (void) unlink(SAVEF);
  440.     return 0;    /* for xxxmain.c test */
  441. }
  442.  
  443.  
  444. /* ----------  END SAVE FILE HANDLING ----------- */
  445.  
  446.  
  447. /* ----------  BEGIN FILE COMPRESSION HANDLING ----------- */
  448.  
  449. /* compress file */
  450. void
  451. compress(filename)
  452. const char *filename;
  453. {
  454. #ifdef COMPRESS
  455.     char cmd[80];
  456.  
  457.     Strcpy(cmd, COMPRESS);
  458.     Strcat(cmd, " ");
  459. # ifdef COMPRESS_OPTIONS
  460.     Strcat(cmd, COMPRESS_OPTIONS);
  461.     Strcat(cmd, " ");
  462. # endif
  463.     Strcat(cmd,filename);
  464.     (void) system(cmd);
  465. #endif
  466. }
  467.  
  468.  
  469. /* uncompress file if it exists */
  470. void
  471. uncompress(filename)
  472. const char *filename;
  473. {
  474. #ifdef COMPRESS
  475.     char cmd[80], cfn[80];
  476.     int fd;
  477.  
  478.     Strcpy(cfn,filename);
  479.     Strcat(cfn,".Z");
  480.     if((fd = open(cfn,O_RDONLY)) >= 0) {
  481.         (void) close(fd);
  482.         Strcpy(cmd, COMPRESS);
  483.         Strcat(cmd, " -d ");        /* uncompress */
  484. # ifdef COMPRESS_OPTIONS
  485.         Strcat(cmd, COMPRESS_OPTIONS);
  486.         Strcat(cmd, " ");
  487. # endif
  488.         Strcat(cmd,cfn);
  489.         (void) system(cmd);
  490.     }
  491. #endif
  492. }
  493.  
  494. /* ----------  END FILE COMPRESSION HANDLING ----------- */
  495.  
  496.  
  497. /* ----------  BEGIN FILE LOCKING HANDLING ----------- */
  498.  
  499. #ifdef NO_FILE_LINKS    /* implies UNIX */
  500. static int lockfd;    /* for lock_file() to pass to unlock_file() */
  501. #endif
  502.  
  503. #if defined(UNIX) || defined(VMS)
  504. #define HUP    if(!done_hup)
  505.  
  506. static char *
  507. make_lockname(filename)
  508. const char *filename;
  509. {
  510.     static char lockname[BUFSZ];
  511.  
  512. # ifdef NO_FILE_LINKS
  513.     Strcpy(lockname, LOCKDIR);
  514.     Strcat(lockname, "/");
  515.     Strcat(lockname, filename);
  516. # else
  517.     Strcpy(lockname, filename);
  518. # endif
  519. # ifdef VMS
  520.       {
  521.     char *semi_colon = rindex(lockname, ';');
  522.     if (semi_colon) *semi_colon = '\0';
  523.       }
  524.     Strcat(lockname, ".lock;1");
  525. # else
  526.     Strcat(lockname, "_lock");
  527. # endif
  528.     return lockname;
  529. }
  530. #endif  /* UNIX || VMS */
  531.  
  532.  
  533. /* lock a file */
  534. boolean
  535. lock_file(filename, retryct)
  536. const char *filename;
  537. int retryct;
  538. {
  539. #if defined(UNIX) || defined(VMS)
  540.     char *lockname;
  541.  
  542.     lockname = make_lockname(filename);
  543.  
  544. # ifdef NO_FILE_LINKS
  545.     while ((lockfd = open(lockname, O_RDWR|O_CREAT|O_EXCL, 0666)) == -1) {
  546. # else
  547.     while (link(filename, lockname) == -1) {
  548. # endif
  549.         register int errnosv = errno;
  550.  
  551.         switch (errnosv) {    /* George Barbanis */
  552.             case ENOENT:
  553.             HUP raw_printf("Can't find file %s to lock!", filename);
  554.             return FALSE;
  555.             case EACCES:
  556.             HUP raw_printf("No write permission to lock %s!",
  557.                        filename);
  558.             return FALSE;
  559.             case EEXIST:
  560.             break;    /* retry checks below */
  561.             default:
  562.             HUP perror(lockname);
  563.             HUP raw_printf(
  564.                      "Cannot lock %s for unknown reason (%d).",
  565.                        filename, errnosv);
  566.             return FALSE;
  567.         }
  568.  
  569.         if (!retryct--) {
  570.             HUP (void) raw_print("I give up.  Sorry.");
  571.             HUP raw_printf("Perhaps there is an old %s around?",
  572.                        lockname);
  573.             return FALSE;
  574.         }
  575.  
  576.         HUP raw_printf("Waiting for access to %s.  (%d retries left).",
  577.                    filename, retryct);
  578. # if defined(SYSV) || defined(ULTRIX) || defined(VMS)
  579.         (void)
  580. # endif
  581.             sleep(1);
  582.     }
  583. #endif  /* UNIX || VMS */
  584.     return TRUE;
  585. }
  586.  
  587.  
  588. #ifdef VMS    /* for unlock_file, use the unlink() routine in vmsunix.c */
  589. # ifdef unlink
  590. #  undef unlink
  591. # endif
  592. # define unlink(foo) vms_unlink(foo)
  593. #endif
  594.  
  595. /* unlock file, which must be currently locked by lock_file */
  596. void
  597. unlock_file(filename)
  598. const char *filename;
  599. {
  600. #if defined(UNIX) || defined(VMS)
  601.     char *lockname;
  602.  
  603.     lockname = make_lockname(filename);
  604.  
  605.     if (unlink(lockname) < 0)
  606.         HUP raw_printf("Can't unlink %s.", lockname);
  607. # ifdef NO_FILE_LINKS
  608.     (void) close(lockfd);
  609. # endif
  610.  
  611. #endif  /* UNIX || VMS */
  612. }
  613.  
  614. /* ----------  END FILE LOCKING HANDLING ----------- */
  615.  
  616.  
  617. /* ----------  BEGIN CONFIG FILE HANDLING ----------- */
  618.  
  619. const char *configfile =
  620. #ifdef UNIX
  621.             ".nethackrc";
  622. #else
  623. #ifdef MAC
  624.             "NetHack defaults";
  625. #else
  626.             "NetHack.cnf";
  627. #endif
  628. #endif
  629.  
  630. static FILE *FDECL(fopen_config_file, (const char *));
  631. static int FDECL(get_uchars, (FILE *, char *, char *, uchar *, int, const char *));
  632. int FDECL(parse_config_line, (FILE *, char *, char *, char *));
  633.  
  634. #ifndef MFLOPPY
  635. #define fopenp fopen
  636. #endif
  637.  
  638. static FILE *
  639. fopen_config_file(filename)
  640. const char *filename;
  641. {
  642.     FILE *fp;
  643. #if defined(UNIX) || defined(VMS)
  644.     char    tmp_config[BUFSZ];
  645. #endif
  646.  
  647.     /* "filename" is an environment variable, so it should hang around */
  648.     if (filename && ((fp = fopenp(filename, "r")) != (FILE *)0)) {
  649.         configfile = filename;
  650.         return(fp);
  651.     }
  652.  
  653. #if defined(MICRO) || defined(MAC)
  654.     if ((fp = fopenp(configfile, "r")) != (FILE *)0)
  655.         return(fp);
  656. #else
  657. # ifdef VMS
  658.     if ((fp = fopenp("nethackini", "r")) != (FILE *)0) {
  659.         configfile = "nethackini";
  660.         return(fp);
  661.     }
  662.     if ((fp = fopenp("sys$login:nethack.ini", "r")) != (FILE *)0) {
  663.         configfile = "nethack.ini";
  664.         return(fp);
  665.     }
  666.     Sprintf(tmp_config, "%s%s", getenv("HOME"), "NetHack.cnf");
  667.     if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  668.         return(fp);
  669. # else    /* should be only UNIX left */
  670.     Sprintf(tmp_config, "%s/%s", getenv("HOME"), ".nethackrc");
  671.     if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
  672.         return(fp);
  673. # endif
  674. #endif
  675.     return (FILE *)0;
  676.  
  677. }
  678.  
  679.  
  680. /*
  681.  * Retrieve a list of integers from a file into a uchar array.
  682.  *
  683.  * NOTE:  This routine is unable to read a value of 0.
  684.  */
  685. static int
  686. get_uchars(fp, buf, bufp, list, size, name)
  687.     FILE *fp;        /* input file pointer */
  688.     char *buf;        /* read buffer, must be of size BUFSZ */
  689.     char *bufp;        /* current pointer */
  690.     uchar *list;    /* return list */
  691.     int  size;        /* return list size */
  692.     const char *name;        /* name of option for error message */
  693. {
  694.     unsigned int num = 0;
  695.     int count = 0;
  696.  
  697.     while (1) {
  698.     switch(*bufp) {
  699.         case ' ':  case '\0':
  700.         case '\t': case '\n':
  701.         if (num) {
  702.             list[count++] =  num;
  703.             num = 0;
  704.         }
  705.         if (count == size || !*bufp) return count;
  706.         bufp++;
  707.         break;
  708.  
  709.         case '0': case '1': case '2': case '3':
  710.         case '4': case '5': case '6': case '7':
  711.         case '8': case '9':
  712.         num = num*10 + (*bufp-'0');
  713.         bufp++;
  714.         break;
  715.  
  716.         case '\\':
  717.             if (fp == (FILE *)0)
  718.             goto gi_error;
  719.         do  {
  720.             if (!fgets(buf, BUFSZ, fp)) goto gi_error;
  721.         } while (buf[0] == '#');
  722.         bufp = buf;
  723.         break;
  724.  
  725.         default:
  726. gi_error:
  727.         raw_printf("Syntax error in %s", name);
  728.         wait_synch();
  729.         return count;
  730.     }
  731.     }
  732.     /*NOTREACHED*/
  733. }
  734.  
  735. /*ARGSUSED*/
  736. int
  737. parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)
  738. FILE        *fp;
  739. char        *buf;
  740. char        *tmp_ramdisk;
  741. char        *tmp_levels;
  742. {
  743.     char        *bufp, *altp;
  744.  
  745.     if (*buf == '#')
  746.         return 1;
  747.  
  748.     /* remove trailing whitespace */
  749.     bufp = eos(buf);
  750.     while (--bufp > buf && isspace(*bufp))
  751.         continue;
  752.  
  753.     if (bufp <= buf)
  754.         return 1;        /* skip all-blank lines */
  755.     else
  756.         *(bufp + 1) = '\0';    /* terminate line */
  757.  
  758.     /* find the '=' or ':' */
  759.     bufp = index(buf, '=');
  760.     altp = index(buf, ':');
  761.     if (!bufp || (altp && altp < bufp)) bufp = altp;
  762.     if (!bufp) return 0;
  763.  
  764.     /* skip  whitespace between '=' and value */
  765.     do { ++bufp; } while (isspace(*bufp));
  766.  
  767.     /* Go through possible variables */
  768.     if (!strncmpi(buf, "OPTIONS", 4)) {
  769.         parseoptions(bufp, TRUE, TRUE);
  770.         if (plname[0])        /* If a name was given */
  771.             plnamesuffix();    /* set the character class */
  772. #ifdef MICRO
  773.     } else if (!strncmpi(buf, "HACKDIR", 4)) {
  774.         (void) strncpy(hackdir, bufp, PATHLEN);
  775. # ifdef MFLOPPY
  776.     } else if (!strncmpi(buf, "RAMDISK", 3)) {
  777.                 /* The following ifdef is NOT in the wrong
  778.                  * place.  For now, we accept and silently
  779.                  * ignore RAMDISK */
  780. #  ifndef AMIGA
  781.         (void) strncpy(tmp_ramdisk, bufp, PATHLEN);
  782. #  endif
  783. # endif
  784.     } else if (!strncmpi(buf, "LEVELS", 4)) {
  785.         (void) strncpy(tmp_levels, bufp, PATHLEN);
  786.  
  787.     } else if (!strncmpi(buf, "SAVE", 4)) {
  788.         char *ptr;
  789.         if (ptr = index(bufp, ';')) {
  790.             *ptr = '\0';
  791. # ifdef MFLOPPY
  792.             if (*(ptr+1) == 'n' || *(ptr+1) == 'N') {
  793.                 extern    int saveprompt;
  794.                 saveprompt = FALSE;
  795.             }
  796. # endif
  797.     }
  798.         (void) strncpy(SAVEP, bufp, PATHLEN);
  799.         append_slash(SAVEP);
  800. #endif /* MICRO */
  801.     } else if(!strncmpi(buf, "CHARACTER", 4)) {
  802.         (void) strncpy(pl_character, bufp, PL_CSIZ);
  803.     } else if(!strncmpi(buf, "DOGNAME", 3)) {
  804.         (void) strncpy(dogname, bufp, 62);
  805.     } else if(!strncmpi(buf, "CATNAME", 3)) {
  806.         (void) strncpy(catname, bufp, 62);
  807.     } else if(!strncmpi(buf, "NAME", 4)) {
  808.         (void) strncpy(plname, bufp, PL_NSIZ);
  809.         plnamesuffix();
  810.     } else if (!strncmpi(buf, "GRAPHICS", 4)) {
  811.         uchar   translate[MAXPCHARS];
  812.         int   len;
  813.  
  814.         len = get_uchars(fp, buf, bufp, translate,
  815.                     MAXPCHARS, "GRAPHICS");
  816.         assign_graphics(translate, len);
  817.     } else if (!strncmpi(buf, "OBJECTS", 3)) {
  818.         /* oc_syms[0] is the RANDOM object, unused */
  819.         (void) get_uchars(fp, buf, bufp, &(oc_syms[1]),
  820.                     MAXOCLASSES-1, "OBJECTS");
  821.     } else if (!strncmpi(buf, "MONSTERS", 3)) {
  822.         /* monsyms[0] is unused */
  823.         (void) get_uchars(fp, buf, bufp, &(monsyms[1]),
  824.                     MAXMCLASSES-1, "MONSTERS");
  825. #ifdef AMIGA
  826.     } else if (!strncmpi(buf, "PATH", 4)) {
  827.         (void) strncpy(PATH, bufp, PATHLEN);
  828.     } else if (!strncmpi(buf, "PENS", 3)) {
  829.         int i;
  830.         char *t;
  831.         extern unsigned short amii_curmap[];
  832.         for (i = 0, t = strtok(bufp, ",");
  833.                 t && i < 8;
  834.                 t = strtok(NULL, ","), ++i) {
  835.             sscanf(t, "%hx", &amii_curmap[i]);
  836.         }
  837.         amii_setpens();
  838. #endif
  839.     } else
  840.         return 0;
  841.     return 1;
  842. }
  843.  
  844. void
  845. read_config_file(filename)
  846. const char *filename;
  847. {
  848. #define tmp_levels    (char *)0
  849. #define tmp_ramdisk    (char *)0
  850.  
  851. #ifdef MICRO
  852. #undef tmp_levels
  853.     char    tmp_levels[PATHLEN];
  854. # ifdef MFLOPPY
  855. #  ifndef AMIGA
  856. #undef tmp_ramdisk
  857.     char    tmp_ramdisk[PATHLEN];
  858. #  endif
  859. # endif
  860. #endif
  861.     char    buf[BUFSZ];
  862.     FILE    *fp;
  863.  
  864. #if defined(MAC)
  865.     {
  866.         long nul = 0L ;
  867.         Str255 volName ;
  868.         /*
  869.          * We should try and get this data from a rsrc, in the profile file
  870.          * the user double-clicked... This data should be saved with the
  871.          * save file in the resource fork, AND be saveable in "stationery"
  872.          */
  873.         GetVol ( volName , & theDirs . dataRefNum ) ;
  874.         GetWDInfo ( theDirs . dataRefNum , & theDirs . dataRefNum , & theDirs .
  875.             dataDirID , & nul ) ;
  876.         if ( volName [ 0 ] > 31 ) volName [ 0 ] = 31 ;
  877.         for ( nul = 1 ; nul <= volName [ 0 ] ; nul ++ ) {
  878.             if ( volName [ nul ] == ':' ) {
  879.                 volName [ nul ] = 0 ;
  880.                 volName [ 0 ] = nul - 1 ;
  881.                 break ;
  882.             }
  883.         }
  884.         BlockMove ( volName , theDirs . dataName , 32L ) ;
  885.     }
  886. #endif /* MAC */
  887.  
  888.     if (!(fp = fopen_config_file(filename))) return;
  889.  
  890. #ifdef MICRO
  891. # ifdef MFLOPPY
  892. #  ifndef AMIGA
  893.     tmp_ramdisk[0] = 0;
  894. #  endif
  895. # endif
  896.     tmp_levels[0] = 0;
  897. #endif
  898.  
  899.     while (fgets(buf, BUFSZ, fp)) {
  900.         if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)) {
  901.             raw_printf("Bad option line:  \"%s\"", buf);
  902.             wait_synch();
  903.         }
  904.     }
  905.     (void) fclose(fp);
  906.  
  907. #ifdef MICRO
  908. # ifdef MFLOPPY
  909.     Strcpy(permbones, tmp_levels);
  910. #  ifndef AMIGA
  911.     if (tmp_ramdisk[0]) {
  912.         Strcpy(levels, tmp_ramdisk);
  913.         if (strcmp(permbones, levels))        /* if not identical */
  914.             ramdisk = TRUE;
  915.     } else
  916. #  endif /* AMIGA */
  917.         Strcpy(levels, tmp_levels);
  918.  
  919.     Strcpy(bones, levels);
  920. # endif /* MFLOPPY */
  921. #endif /* MICRO */
  922.     return;
  923. }
  924.  
  925. /* ----------  END CONFIG FILE HANDLING ----------- */
  926.  
  927. /* ----------  BEGIN SCOREBOARD CREATION ----------- */
  928.  
  929. /* verify that we can write to the scoreboard file; if not, try to create one */
  930. void
  931. check_recordfile(dir)
  932. const char *dir;
  933. {
  934. #if defined(UNIX) || defined(VMS)
  935.     int fd = open(RECORD, O_RDWR, 0);
  936.  
  937.     if (fd >= 0) {
  938. # ifdef VMS    /* must be stream-lf to use UPDATE_RECORD_IN_PLACE */
  939.         if (!file_is_stmlf(fd)) {
  940.             raw_printf(    /* note: assume VMS dir has trailing punct */
  941.           "Warning: scoreboard file %s%s is not in stream_lf format",
  942.                 (dir ? dir : "[]"), RECORD);
  943.             wait_synch();
  944.         }
  945. # endif
  946.         (void) close(fd);    /* RECORD is accessible */
  947.     } else if ((fd = open(RECORD, O_CREAT|O_RDWR, FCMASK)) >= 0) {
  948.         (void) close(fd);    /* RECORD newly created */
  949. # if defined(VMS) && !defined(SECURE)
  950.         /* Re-protect RECORD with world:read+write+execute+delete access. */
  951.         (void) chmod(RECORD, FCMASK | 007); /* allow everyone full access */
  952. # endif /* VMS && !SECURE */
  953.     } else {
  954.         raw_printf("Warning: cannot write scoreboard file %s/%s",
  955.             (dir ? dir : "."), RECORD);
  956.         wait_synch();
  957.     }
  958. #endif  /* !UNIX && !VMS */
  959.  
  960. #ifdef MICRO
  961.     int fd;
  962.     char tmp[PATHLEN];
  963.  
  964. # ifdef OS2_CODEVIEW   /* explicit path on opening for OS/2 */
  965.     Strcpy(tmp, dir);
  966.     append_slash(tmp);
  967.     Strcat(tmp, RECORD);
  968. # else
  969.     Strcpy(tmp, RECORD);
  970. # endif
  971.  
  972.     if ((fd = open(tmp, O_RDWR)) < 0) {
  973.         /* try to create empty record */
  974. # ifdef AZTEC_C
  975.         /* Aztec doesn't use the third argument */
  976.         if ((fd = open(tmp, O_CREAT|O_RDWR)) < 0) {
  977. # else
  978.         if ((fd = open(tmp, O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) < 0) {
  979. # endif
  980.         raw_printf("Warning: cannot write record %s", tmp);
  981.         wait_synch();
  982.         } else
  983.         (void) close(fd);
  984.     } else        /* open succeeded */
  985.         (void) close(fd);
  986. #else /* MICRO */
  987.  
  988. # ifdef MAC
  989.     int fd = macopen ( RECORD , O_RDWR | O_CREAT , TEXT_TYPE ) ;
  990.  
  991.     if ( fd < 0 ) {
  992.         raw_printf ( "Warning: cannot write %s" , RECORD ) ;
  993.     } else {
  994.         close ( fd ) ;
  995.     }
  996. # endif /* MAC */
  997.  
  998. #endif /* MICRO */
  999. }
  1000.  
  1001. /* ----------  END SCOREBOARD CREATION ----------- */
  1002.  
  1003.  
  1004. /*files.c*/
  1005.